package com.baomidou;

import com.baomidou.config.GCPDatasourceConfig;
import com.baomidou.config.GCPGlobalConfig;
import com.baomidou.config.GCPTableConfig;
import com.baomidou.mybatisplus.annotation.DbType;
import com.google.common.base.Strings;
import net.sf.cglib.beans.BeanCopier;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;

import java.util.ArrayList;
import java.util.List;

@Mojo(name = "generate", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
public class GCPMojo extends AbstractMojo {
    @Parameter(required = true)
    private GCPDatasourceConfig datasource;

    @Parameter
    private GCPTableConfig tableConfig;

    @Parameter
    private GCPGlobalConfig globalConfig;

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        try {
            new GCPGenerator(prepareConfig()).execute();
        } catch (Throwable e) {
            getLog().error("execute encounter error.", e);
        }
    }

    private GCPConfig prepareConfig() {
        GCPConfig config = new GCPConfig();
        BeanCopier beanCopier = BeanCopier.create(datasource.getClass(), config.getClass(), false);
        beanCopier.copy(datasource, config, null);
        initDb(config);
        initTable(config, tableConfig);
        beanCopier = BeanCopier.create(globalConfig.getClass(), config.getClass(), false);
        beanCopier.copy(globalConfig, config, null);
        return config;
    }

    private void initTable(GCPConfig config, GCPTableConfig tableConfig) {
        config.setIncludeTables(split(tableConfig.getIncludeTables()));
        config.setExcludeTables(split(tableConfig.getExcludeTables()));
        config.setTablePrefixes(split(tableConfig.getTablePrefixes()));
        config.setTableSuffixes(split(tableConfig.getTableSuffixes()));
        config.setFieldPrefixes(split(tableConfig.getFieldPrefixes()));
        config.setFieldSuffixes(split(tableConfig.getFieldSuffixes()));
        config.setIgnoreColumns(split(tableConfig.getIgnoreColumns()));
    }

    private String[] split(String value) {
        if (Strings.isNullOrEmpty(value)) {
            return new String[]{};
        }
        List<String> valueList = new ArrayList<>();
        String[] values;
        if (value.contains(",")) {
            values = value.split(",");
        } else if (value.contains("\n")) {
            values = value.split("\n");
        } else {
            values = value.split(" ");
        }
        for (String str : values) {
            str = str.trim();
            if (!Strings.isNullOrEmpty(str)) {
                valueList.add(str);
            }
        }
        String[] result = new String[valueList.size()];
        return valueList.toArray(result);
    }

    private void initDb(GCPConfig config) {
        String dbUrl = "";
        String driver = "";
        if (config.getDbType() == null) {
            throw new IllegalArgumentException("db type cannot be null!");
        } else if (config.getDbType() == DbType.MYSQL) {
            // mysql
            dbUrl = "jdbc:mysql://" + config.getHostname() + ":" + config.getPort() + "/" + config.getSchema();
            driver = "com.mysql.cj.jdbc.Driver";
        } else if (config.getDbType() == DbType.ORACLE) {
            dbUrl = "jdbc:oracle:thin:@" + config.getHostname() + ":" + config.getPort() + ":" + config.getSchema();
            driver = "oracle.jdbc.OracleDriver";
        } else if (config.getDbType() == DbType.SQL_SERVER) {
            dbUrl = "jdbc:sqlserver://" + config.getHostname() + ":" + config.getPort() + ";DatabaseName=" + config.getSchema() + ";trustServerCertificate=true";
            driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
        } else {
            throw new IllegalArgumentException("unsupported db type [" + config.getDbType() + "]!");
        }
        config.setDbUrl(dbUrl);
        config.setDriver(driver);
    }
}
